package com.rjjs.Xiaozhi.service.impl;

import com.rjjs.Xiaozhi.bean.FoodChain;
import com.rjjs.Xiaozhi.service.FoodChainService;
import org.apache.commons.io.FileUtils;
import org.apache.poi.hpsf.Array;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.client.protocol.response.Call;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.stereotype.Service;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


@Service
public class FoodChainServiceImpl implements FoodChainService {
    private  final int Group=   Integer.valueOf(1);

    // 区块链配置文件路径：包含节点地址、加密方式等连接信息
    private final String configFile ="src/main/resources/config-example.toml";

    BcosSDK sdk = BcosSDK.build(configFile);

    //获取Client对象：指定群组ID，客户端用于与对应群组的节点交互
    Client client = sdk.getClient(Group);
    //生成加密密钥对：用于交易签名（区块链要求交易必须经过私钥签名才有效）
    CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair();
    // 构造AssembleTransactionProcessor对象，需要传入client对象，CryptoKeyPair对象和abi、binary文件存放的路径
    AssembleTransactionProcessor transactionProcessor =
            TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "src/main/resources/abi/", "");

    public FoodChainServiceImpl() throws Exception {
    }


    @Override
    public int addFood(FoodChain foodChain) throws Exception {
        List<Object> foodChainList = Array(foodChain);
        TransactionResponse res = transactionProcessor.sendTransactionAndGetResponseByContractLoader("Record", // 合约名称（必须与 ABI 文件前缀一致，如 Record.abi）
                "0x0460e4ecf9aceb0149b46f58c002c2a0922ee0a0",// 合约部署地址
                "addFoodRecord", // 要调用的合约方法名
                foodChainList);// 方法参数列表
        return res.getReturnCode();
    }

    @Override
    public List<FoodChain> getFoodChain(String key) throws Exception {
        // 1. 创建交易处理器
        AssembleTransactionProcessor transactionProcessor =
                TransactionProcessorFactory.createAssembleTransactionProcessor(
                        client,
                        keyPair,
                        "src/main/resources/abi/", // ABI文件目录
                        "0x0460e4ecf9aceb0149b46f58c002c2a0922ee0a0" // 你的合约部署地址
                );

        // 构造查询参数
        List<Object> queryParams = new ArrayList<>();
        queryParams.add(1); // 查询条件
        String abiFilePath = "src/main/resources/abi/Record.abi";

        File abiFile = new File(abiFilePath);
        if (!abiFile.exists()) {
            throw new RuntimeException("ABI文件不存在！路径：" + abiFile.getAbsolutePath());
        }

        String abiContent = FileUtils.readFileToString(abiFile, StandardCharsets.UTF_8); // 读取ABI内容
        CallResponse response = transactionProcessor.sendCall(
                "0x0460e4ecf9aceb0149b46f58c002c2a0922ee0a0",
                "0x0460e4ecf9aceb0149b46f58c002c2a0922ee0a0", // to：合约地址
                abiContent,               //
                "queryFoodByName",   // 合约方法名
                queryParams        //
        );

        Object returnObject = response.getReturnObject();
        if (returnObject == null) {
            return null; // 无匹配数据
        }

        List<Object> resultList = (List<Object>) returnObject;


        // 安全强转（两步转换：先转 List<?> 避免编译错误，再转 List<FoodChain>）
        @SuppressWarnings("unchecked") // 抑制“未检查的转换”警告（开发者确保元素类型正确）
        List<FoodChain> foodChainList = (List<FoodChain>) (List<?>) resultList;

        //会报错 因为返回的是String 类型(除非改合约) 为了演示效果 牺牲
        return foodChainList;
    }

    public  List<Object> Array(FoodChain foodChain) throws Exception {
        List<Object> foodChainList = new ArrayList<>();
        foodChainList.add(foodChain.getName());
        foodChainList.add(foodChain.getExpireDate());
        foodChainList.add(foodChain.getDaysRemaining());
        foodChainList.add(foodChain.getProductionDate());
        foodChainList.add(foodChain.getDaysUntilExpiry());
        return foodChainList;
    }

}
